/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.delivery.web;

import com.mycompany.delivery.dto.ContactDTO;
import com.mycompany.delivery.dto.DTOState;
import com.mycompany.delivery.dto.DeliveryDTO;
import com.mycompany.delivery.dto.UserDTO;
import com.mycompany.delivery.servicelayer.ContactService;
import com.mycompany.delivery.servicelayer.DeliveryService;
import com.mycompany.delivery.servicelayer.UserService;
import com.mycompany.delivery.validation.CourierSpringValidator;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;

/**
 *
 * @author Katarína Hrabovská <katarina.hrabovska1992@gmail.com>
 */
@Controller
@RequestMapping("/courier")
public class CourierController {

    final static Logger log = LoggerFactory.getLogger(CourierController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private DeliveryService deliveryService;

    @Autowired
    private ContactService contactServices;

    @Autowired
    private MessageSource messageSource;

    @ModelAttribute("contacts")
    public List<ContactDTO> allContact() {
        log.debug("allContacts()");
        return contactServices.getAllContacts();
    }

    @ModelAttribute("couriers")
    public List<UserDTO> allCouriers() {
        log.debug("allCouriers()");
        return userService.getAllCouriers();
    }

    @RequestMapping(value = "/formR", method = RequestMethod.GET)
    public String rece(Model model) {
        log.debug("rece()");
        model.addAttribute("courier", new UserDTO());
        return "courier/formR";
    }

    @RequestMapping(value = "/find", method = RequestMethod.GET)
    public String findDef(Model model) {
        model.addAttribute("string", new String());

        model.addAttribute("contacts", new ArrayList<ContactDTO>());
        log.debug("find(model={})", model);
        return "courier/formR";
    }

    @RequestMapping(value = "/find/{name}", method = RequestMethod.GET)
    public String findDef(@PathVariable String name, Model model) {
        model.addAttribute("string", new String());

        model.addAttribute("contacts", contactServices.findContactBySurname(name));
        log.debug("find(model={})", model);
        return "courier/formR";
    }

    @RequestMapping(value = "/new/{id}", method = RequestMethod.POST)
    public String newContact(@PathVariable Long id, Model model, UriComponentsBuilder builder) {
        return "redirect:" + builder.path("/courier/new/" + id).build();
    }

    @RequestMapping(value = "/new/{id}", method = RequestMethod.GET)
    public String newContact2(@PathVariable Long id, Model model) {
        ContactDTO c = contactServices.find(id);
        log.debug("listNova()");
        model.addAttribute("contact", id);
        UserDTO u = new UserDTO();
        u.setContact(c);
        model.addAttribute("courier", u);
        return "courier/new";
    }

    @RequestMapping(value = "/find", method = RequestMethod.POST)
    public String finded(@RequestParam("name") String name, Model model, UriComponentsBuilder builder, Locale locale) {

        String n = name;
        log.debug("atribut1 {} loc {}", name, locale);
        try {
            n = UriUtils.encodePath(name, "UTF-8");
        } catch (Exception ex) {
        }
        log.debug("atribut2 {}", n);
        log.debug("find(model={})", model);

        return "redirect:" + builder.path("/courier/find/" + n).build();
    }

    @RequestMapping(value = "/new", method = RequestMethod.GET)
    public String listNovy(Model model) {
        log.debug("listNovy()");
        model.addAttribute("courier", new UserDTO());
        return "courier/new";
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
    public String delete(@PathVariable long id, RedirectAttributes redirectAttributes, Locale locale, UriComponentsBuilder uriBuilder) {
        log.debug("delete({})", id);
        UserDTO courier = userService.findCourier(id);
        userService.removeCourier(courier);
        redirectAttributes.addFlashAttribute(
                "message",
                messageSource.getMessage("courier.delete.message", new Object[]{courier.getId()}, locale)
        );
        return "redirect:" + uriBuilder.path("/courier/list").build();
    }

    @RequestMapping(value = "/update/{id}", method = RequestMethod.GET)
    public String update_form(@PathVariable long id, Model model) {
        UserDTO user = userService.findCourier(id);
        model.addAttribute("courier", user);
        log.debug("update_form(model={})", model);
        return "courier/edit";
    }

    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String list(Model model) {
        log.debug("list()");
        model.addAttribute("courier", new UserDTO());
        return "courier/list";
    }

    @RequestMapping(value = "/deliveries/{id}", method = RequestMethod.GET)
    public String deliveries(@PathVariable long id, Model model) {
        log.debug("list() couriers delivery");
        UserDTO u = userService.findCourier(id);
        List<DeliveryDTO> del = deliveryService.getDeliveriesByStateFromCourier(u, DTOState.UNPROCESSED);
        List<DeliveryDTO> del2 = deliveryService.getDeliveriesByStateFromCourier(u, DTOState.RECEIVEDBYCOURIER);
        model.addAttribute("unprocessedDeliveries", del);
        model.addAttribute("recievedDeliveries", del2);
        model.addAttribute("courier", u);
        return "courier/listDel";
    }

    @RequestMapping(value = "/deliveries/{id}/{delId}", method = RequestMethod.POST)
    public String deliveriesWork(@PathVariable long id, @PathVariable long delId, Model model, UriComponentsBuilder uriBuilder) {
        log.debug("list() couriers delivery post");
        return "redirect:" + uriBuilder.path("/courier/deliveries/" + id + "/" + delId).build();
    }

    @RequestMapping(value = "/deliveries/{id}/{delId}", method = RequestMethod.GET)
    public String deliveriesWorkGet(@PathVariable long id, @PathVariable long delId, Model model, UriComponentsBuilder uriBuilder) {
        log.debug("list() couriers delivery post get");
        UserDTO u = userService.findCourier(id);
        DeliveryDTO del = deliveryService.find(delId);
        log.debug(del.toString() + " delivery");
        if (del.getState() == DTOState.UNPROCESSED) {
            del.setState(DTOState.RECEIVEDBYCOURIER);
            log.debug("couriers delivery set recieved");
            deliveryService.update(del);
        } else if (del.getState() == DTOState.RECEIVEDBYCOURIER) {
            del.setState(DTOState.DELIVERED);
            del.setDeliveryDate(new Date());
            deliveryService.update(del);
            log.debug("couriers delivery set delivered");
        }
        return "redirect:" + uriBuilder.path("/courier/deliveries/" + id).build();

    }

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addValidators(new CourierSpringValidator());
    }

    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public String update(@Valid @ModelAttribute UserDTO courier, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes,  Locale locale, UriComponentsBuilder uriBuilder) {
        log.debug("update(locale={}, courier={})", locale, courier);
        CourierSpringValidator validator = new CourierSpringValidator();
        validator.validate(courier, bindingResult);
        if (bindingResult.hasErrors()) {
            log.debug("binding errors");
            for (ObjectError ge : bindingResult.getGlobalErrors()) {
                log.debug("ObjectError: {}", ge);
            }
            for (FieldError fe : bindingResult.getFieldErrors()) {
                log.debug("FieldError: {}", fe);
                
                 model.addAttribute("courier", courier);
           String mailmessage = messageSource.getMessage(fe,  locale);
           model.addAttribute("message", mailmessage);
            }
            return courier.getId() == null ? "courier/list" : "courier/edit";
        }
        
        /*
            if (courier.getLogin() == null || "".equals(courier.getLogin())) {
                redirectAttributes.addFlashAttribute(
                        "message",
                        messageSource.getMessage("courier.nologin", new Object[]{courier}, locale)
                );
                return courier.getId() == null ? "courier/list" : "courier/edit";
            }
            
             if (courier.getContact() == null) {
                redirectAttributes.addFlashAttribute(
                        "message",
                        messageSource.getMessage("user.noContact", new Object[]{courier}, locale)
                );
                return courier.getId() == null ? "courier/list" : "courier/edit";
            }
            
             if (!(courier.getLogin().matches("^[a-zA-Z0-9_-]{5,20}$"))) {
                redirectAttributes.addFlashAttribute(
                        "message",
                        messageSource.getMessage("courier.wrongLogin", new Object[]{courier.getLogin()}, locale)
                );
                return courier.getId() == null ? "courier/list" : "courier/edit";
            }*/
            
             courier.setContact(contactServices.find(courier.getContact().getId()));
            if (courier.getId() == null) {
            if (userService.findUserByLogin(courier.getLogin()) != null) {
                redirectAttributes.addFlashAttribute(
                        "message",
                        messageSource.getMessage("courier.login.notUnique", new Object[]{courier.getLogin()}, locale)
                );
                return "redirect:" + uriBuilder.path("/courier/list").build();
            }
            userService.createCourier(courier);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("courier.add.message", new Object[]{courier.getId()}, locale)
            );
        } else {
            userService.updateCourier(courier);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("courier.updated.message", new Object[]{courier.getId()}, locale)
            );
        }
        return "redirect:" + uriBuilder.path("/courier/list").build();
    }
}
